package main

import (
	"fmt"
	"sync"
	// "time"
)

// 并发输出100个数字的方法
func main() {
	// 1最笨的方法 直接使用协程并发输出数据，需要通过time.sleep等待时间防止主程序退出
	// for i := 0; i < 100; i++ {
	// 	go fmt.Println(i)
	// }
	// time.Sleep(time.Second)

	//2推荐方法 使用通道来完成异步并发输出 chan有进必须有出 要不会阻塞代码
	c := make(chan bool, 100) //创建chan通道类型容量为100 的布尔型变量
	for i := 0; i < 100; i++ {
		// 调用闭包需要把i传入
		go func(i int) {
			fmt.Println(i)
			c <- true // 通道中赋值
		}(i)
	}
	// 建一个for循环来一次读出管道里的数据
	for i := 0; i < 100; i++ {
		<-c //从管道中取数据要不管道会阻塞程序无法执行
	}

	// 由于使用chan比较大 ，可以使用waitGroup WaitGroup 对象内部有一个计数器，最初从0开始，它有三个方法：Add(), Done(), Wait() 用来控制计数器的数量。Add(n) 把计数器设置为n ，Done() 每次把计数器-1 ，wait() 会阻塞代码的运行，直到计数器地值减为0。
	// wg := sync.WaitGroup{}
	// wg.Add(100)
	// for i := 0; i < 100; i++ {
	// 	go f(i, &wg)
	// }
	// wg.Wait() // 阻塞线程主线程
}

// 一定要通过指针传值，不然进程会进入死锁状态
func f(i int, wg *sync.WaitGroup) {
	fmt.Println(i)
	wg.Done()
}
